﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows;
using System.Windows.Navigation;

using PasswordProvider.ViewModel.Properties;
using PasswordProvider.ViewModel.Framework;

namespace PasswordProvider.ViewModel
{
    public class SequentialPageViewerViewModel : VisualViewModel, IRequestClose
    {
        private List<VisualViewModel> _openedViews;
        private Type[] _viewTypes;

        internal SequentialPageViewerViewModel(Type[] viewTypes)
            : base()
        {
            _openedViews = new List<VisualViewModel>();
            _viewTypes = viewTypes;
        }

        #region ICompleteTask Members

        public event EventHandler CloseRequested;

        #endregion

        #region Public Interface

        public VisualViewModel CurrentView
        {
            get
            {
                return _navigationService.Content as VisualViewModel;   
            }
        }

        public NavigationService NavigationService
        {
            set 
            {
                if (value != null)
                {
                    _navigationService = value;
                    _navigationService.Navigated += new NavigatedEventHandler(NavigationService_Navigated);
                    if (CurrentView == null)
                    {
                        GoToFirst();
                    }
                }
            }
            get { return _navigationService; }
        }  private NavigationService _navigationService;

        public VisualViewModel Header
        {
            get
            {
                if (_header == null)
                {
                    string name = CurrentView == null ? null : CurrentView.DisplayName;
                    Visibility visibility = name == null ? Visibility.Collapsed : Visibility.Visible;
                    _header = new VisualViewModel(name, visibility);
                }
                return _header;
            }
        } private VisualViewModel _header;

        /// <summary>
        /// Back command
        /// </summary>
        public CommandViewModel BackCommand
        {
            get 
            {
                if (_backCommand == null)
                {
                    _backCommand = new CommandViewModel(
                        Strings.SequentialPageViewer_Back_DisplayName,
                        new RelayCommand(param => BackCommandExecuted()));
                    _backCommand.Visibility = Visibility.Hidden;
                }
                return _backCommand;
            }
        } private CommandViewModel _backCommand;

        /// <summary>
        /// Forward command
        /// </summary>
        public CommandViewModel ForwardCommand
        {
            get
            {
                if (_forwardCommand == null)
                {
                    _forwardCommand = new CommandViewModel(
                        Strings.SequentialPageViewer_Forward_DisplayName,
                        new RelayCommand(param => ForwardCommandExecuted()));
                }
                return _forwardCommand;
            }
        } private CommandViewModel _forwardCommand;

        /// <summary>
        /// Finish command
        /// </summary>
        public CommandViewModel FinishCommand
        {
            get
            {
                if (_finishCommand == null)
                {
                    _finishCommand = new CommandViewModel(
                        Strings.SequentialPageViewer_Finish_DisplayName,
                        Strings.SequentialPageViewer_Finish_ToolTip,
                        new RelayCommand(param => FinishCommandExecuted()));
                }
                return _finishCommand;
            }
        } private CommandViewModel _finishCommand;

        #endregion // Public Interface

        #region Command Handlers

        private void BackCommandExecuted()
        {
            if (CurrentIndex > 0)
                GoToPrevious();
            else
                FinishCommandExecuted();
        }

        private void ForwardCommandExecuted()
        {
            if (CurrentIndex < _viewTypes.Length - 1)
                GoToNext();
            else
                FinishCommandExecuted();
        }

        private void FinishCommandExecuted()
        {
            foreach (object vm in _openedViews)
            {
                ICommitChanges commit = vm as ICommitChanges;
                if(commit != null)
                    commit.CommitChanges();
            }

            // It is an error if this event is not being handled.
            CloseRequested(this, new EventArgs());
        }

        #endregion // command handlers

        #region Private Helpers

        private VisualViewModel NextView { get; set; }
        private VisualViewModel PrevView { get; set; }
        private int CurrentIndex { get; set; }

        private void GoToNext()
        {
            if (NextView == null) 
                throw new InvalidOperationException("Can't go forward");

            if (_navigationService.CanGoForward)
                _navigationService.GoForward();
            else
                _navigationService.Navigate(NextView);

            CurrentIndex = CurrentIndex + 1;
            PrevView = GetViewModelAt(CurrentIndex - 1);
            NextView = GetViewModelAt(CurrentIndex + 1);
                        
        }

        private void GoToPrevious()
        {
            if(PrevView == null)
                throw new InvalidOperationException("can't go back");

            _navigationService.GoBack();
            CurrentIndex = CurrentIndex - 1;
            PrevView = GetViewModelAt(CurrentIndex - 1);
            NextView = GetViewModelAt(CurrentIndex + 1);
        }

        private void GoToFirst()
        {
            _navigationService.Navigate(GetViewModelAt(0));
            CurrentIndex = 0;
            PrevView = null;
            NextView = GetViewModelAt(1);
        }

        private VisualViewModel GetViewModelAt(int index)
        {
            if ( (index >= _viewTypes.Length) || (index < 0) )
                return null;

            if (_openedViews.Count < index + 1)
            {
                // Create the view model dynamically, if not navigated to, won't be constructed.
                VisualViewModel vm = (VisualViewModel)Activator.CreateInstance(_viewTypes[index], true);
                _openedViews.Add(vm);
                return vm;
            }
            else
                return _openedViews[index];
        }

        void NavigationService_Navigated(object sender, NavigationEventArgs e)
        {
            OnPropertyChanged("CurrentView");
            Header.DisplayName = CurrentView.DisplayName;
            Header.ToolTip = CurrentView.ToolTip;
            if (!String.IsNullOrEmpty(Header.DisplayName))
                Header.Visibility = Visibility.Visible;
            else
                Header.Visibility = Visibility.Collapsed;

            // Setup forward and back commands.
            if (NextView == null)
            {
                ForwardCommand.Visibility = Visibility.Hidden;             
            }
            else
            {                
                ForwardCommand.ToolTip = NextView.ToolTip;
                ForwardCommand.DisplayName = NextView.DisplayName;
                ForwardCommand.Visibility = Visibility.Visible;
            }

            if (PrevView == null)
            {
                BackCommand.Visibility = Visibility.Hidden;                
            }
            else
            {
                BackCommand.ToolTip = PrevView.ToolTip;
                BackCommand.DisplayName = PrevView.DisplayName;
                BackCommand.Visibility = Visibility.Visible;                
            }
        }
        
        #endregion
    }
}
